package com.derekandbritt.booST.endpoints;

import java.io.IOException;
import java.util.List;

import org.opensocial.Client;
import org.opensocial.Request;
import org.opensocial.RequestException;
import org.opensocial.Response;
import org.opensocial.models.Person;
import org.opensocial.services.PeopleService;

import com.derekandbritt.booST.data.OpenSocialFriendCache;
import com.derekandbritt.booST.data.SingleItemCache;
import com.derekandbritt.booST.exceptions.ConnectionException;
import com.derekandbritt.booST.exceptions.DataFormatException;

public class OpenSocialEndpoint {

	private Client client;
	
	private static SingleItemCache<Person> currentUserCache = new SingleItemCache<Person>(null, 86400000); // 1 day
	private static OpenSocialFriendCache friendCache = new OpenSocialFriendCache();

	public OpenSocialEndpoint(Client client) {
	    this.client = client;
	}
	
	public void setClient(Client client) {
	    this.client = client;
	}
	
	public void clearCaches() {
	    currentUserCache.updateCache(null);
	    friendCache.clearCache(); 
	}
	
	public Person fetchPerson() throws ConnectionException, DataFormatException {
		
		//check the cache
		if(currentUserCache.isValid())
			return currentUserCache.getItem();
		
		try {
    		Request request = PeopleService.getViewer();
    		Response response = client.send(request);
    		Person person = response.getEntry();

    	    //set the cache
            currentUserCache.updateCache(person);
            
            return person;
		} catch(IOException e) {
		    throw new ConnectionException("Unable to access the social network.", e);
		} catch (RequestException e) {
		    throw new DataFormatException("Unable to access the social network.", e);
        }
	}
	
	public Person fetchPerson(String personId) throws ConnectionException, DataFormatException {
		
		//check the cache
		if(friendCache.isValid() && friendCache.containsFriend(personId))
			return friendCache.getFriend(personId);
		
        try {
            Request request = PeopleService.getUser(personId);
            Response response = client.send(request);
            Person person = response.getEntry();
            
            return person;
        } catch(IOException e) {
            throw new ConnectionException("Unable to access the social network.", e);
        } catch (RequestException e) {
            throw new DataFormatException("Unable to access the social network.", e);
        }
	}
	
	public List<Person> fetchFriends() throws ConnectionException, DataFormatException {
		
		//check the cache
		if(friendCache.isValid())
			return friendCache.getFriends();
		
        try {
            Request request = PeopleService.getFriends();
            Response response = client.send(request);
            List<Person> friends = response.getEntries();

            //set the cache
            friendCache.updateCache(friends);
            
            return friends;
        } catch(IOException e) {
            throw new ConnectionException("Unable to access the social network.", e);
        } catch (RequestException e) {
            throw new DataFormatException("Unable to access the social network.", e);
        }
	}
	
	public String getPersonId() throws ConnectionException, DataFormatException {
		return getPersonId(fetchPerson());
	}
	
	public static String getPersonId(Person person) throws DataFormatException {
		try {
		    return person.getId();
		    //ONLY works for Plaxo
		    //return (String) person.getFieldAsMap("accounts").get("userid");
		} catch (NullPointerException e) {
			throw new DataFormatException("Error retrieving the user's social network id", e);
		} 
 
	}
	
	public String getFullName(String personId) throws ConnectionException, DataFormatException {
	    Person person = fetchPerson(personId);
	    return (person == null) ? "" : getFullName(person);
	}
	
	public static String getFullName(Person person) throws DataFormatException {
	    return getFirstName(person) + " " + getLastName(person);
	}
	
	public static String getFirstName(Person person) throws DataFormatException {
		try {
	        return (String) person.getFieldAsMap("name").get("givenName");
		} catch (NullPointerException e) {
			throw new DataFormatException("Error retrieving the user's social network id", e);
		} 
	}
	
	public static String getLastName(Person person) throws DataFormatException {
		try {
		    return (String) person.getFieldAsMap("name").get("familyName");
		} catch (NullPointerException e) {
			throw new DataFormatException("Error retrieving the user's social network id", e);
		} 
	}
}
